//----------------------------------Include-------------------------------------
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "mcu.h"
//#include "dbg.h"
//------------------------------------------------------------------------------

//-----------------------------------Macro--------------------------------------
#define _UART              USART1        //PA9--Tx  PA10--Rx
//------------------------------------------------------------------------------
//#define _DMA               DMA1          //DMA1 Channel_2--USART1_TX   Channel_3--USART1_RX
//#define _DMA_NUM_TX        2
//#define _DMA_CHN_TX        DMA1_Channel2
//#define _DMA_NUM_RX        3
//#define _DMA_CHN_RX        DMA1_Channel3
//------------------------------------------------------------------------------
#define _DIR_OUT()         do{;}while(0)
#define _DIR_IN()          do{;}while(0)
//------------------------------------------------------------------------------

//---------------------------------Static Var-----------------------------------
//------------------------------------------------------------------------------

//--------------------------------Static Func-----------------------------------
//------------------------------------------------------------------------------

//--------------------------------Public Func-----------------------------------
void mcu_init_uart1(uint32_t baud)
{
//periph clock
  //下面这个配置可以注释掉，预留下来是为了方便以后选择其它时钟使用
  //默认情况下，USART1和USART6选择的PCLK2，时钟100MHz。
  //USART2，USART3，UART4，UART5，UART6，UART7和UART8选择的时钟是PLCK1，时钟100MHz。
  //RCC_PeriphCLKInitTypeDef    RCC_PeriphClkInit;
  //RCC_PeriphClkInit.PeriphClockSelection  = RCC_PERIPHCLK_USART16;
  //RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
  //HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);

  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_USART1_CLK_ENABLE();

//pin
  //tx pin
  GPIO_InitTypeDef    GPIO_InitStruct;
  GPIO_InitStruct.Pin       = GPIO_PIN_9;
  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull      = GPIO_PULLUP;
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  //rx pin
  GPIO_InitStruct.Pin       = GPIO_PIN_10;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

//uart
  LL_USART_InitTypeDef    USART_InitS;
  LL_USART_StructInit   (&USART_InitS);
  USART_InitS.BaudRate            = baud;
  USART_InitS.DataWidth           = LL_USART_DATAWIDTH_8B;
  USART_InitS.StopBits            = LL_USART_STOPBITS_1;
  USART_InitS.Parity              = LL_USART_PARITY_NONE;
  USART_InitS.TransferDirection   = LL_USART_DIRECTION_TX_RX;
  USART_InitS.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
  USART_InitS.OverSampling        = LL_USART_OVERSAMPLING_16;
  LL_USART_Init(_UART, &USART_InitS);

//interrupt
  SET_BIT(_UART->ICR, USART_ICR_TCCF);    // 清除TC发送完成标志
  SET_BIT(_UART->RQR, USART_RQR_RXFRQ);   // 清除RXNE接收标志
  SET_BIT(_UART->CR1, USART_CR1_RXNEIE);  // 使能RX接受中断

//NVIC
  HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(USART1_IRQn);

//enable
  LL_USART_Enable(_UART);
  
#if 0
//dma
  //periph clock
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  
  //dma--tx
  DMA_InitTypeDef   DMA_InitS;
  DMA_StructInit  (&DMA_InitS);
  
  DMA_DeInit(_DMA_CHN_TX);
  DMA_InitS.DMA_PeripheralBaseAddr = (uint32_t)&_UART->TDR;
  DMA_InitS.DMA_MemoryBaseAddr     = 0;
  DMA_InitS.DMA_DIR                = DMA_DIR_PeripheralDST;
  DMA_InitS.DMA_BufferSize         = 0;
  DMA_InitS.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
  DMA_InitS.DMA_MemoryInc          = DMA_MemoryInc_Enable;
  DMA_InitS.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitS.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
  DMA_InitS.DMA_Mode               = DMA_Mode_Normal;
  DMA_InitS.DMA_Priority           = DMA_Priority_Low;
  DMA_InitS.DMA_M2M                = DMA_M2M_Disable;
  DMA_Init(_DMA_CHN_TX, &DMA_InitS);
  
  //dma--rx
  DMA_DeInit(_DMA_CHN_RX);
  DMA_InitS.DMA_PeripheralBaseAddr = (uint32_t)&_UART->RDR;
  DMA_InitS.DMA_MemoryBaseAddr     = (uint32_t)dbg_get_rcv_addr();
  DMA_InitS.DMA_DIR                = DMA_DIR_PeripheralSRC;
  DMA_InitS.DMA_BufferSize         = dbg_get_rcv_size();
  DMA_InitS.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
  DMA_InitS.DMA_MemoryInc          = DMA_MemoryInc_Enable;
  DMA_InitS.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitS.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
  DMA_InitS.DMA_Mode               = DMA_Mode_Normal;
  DMA_InitS.DMA_Priority           = DMA_Priority_Low;
  DMA_InitS.DMA_M2M                = DMA_M2M_Disable;
  DMA_Init(_DMA_CHN_RX, &DMA_InitS);
  
  //interrupt
  DMA_ITConfig(_DMA_CHN_TX, DMA_IT_TC | DMA_IT_TE , ENABLE);
  DMA_ITConfig(_DMA_CHN_RX, DMA_IT_TC | DMA_IT_TE , ENABLE);
  
  //enable
  DMA_Cmd(_DMA_CHN_RX, ENABLE);
  
  //NVIC
  NVIC_InitTypeDef    NVIC_InitS;
  NVIC_InitS.NVIC_IRQChannel         = DMA1_Channel2_3_IRQn;
  NVIC_InitS.NVIC_IRQChannelPriority = 2;
  NVIC_InitS.NVIC_IRQChannelCmd      = ENABLE;
  NVIC_Init(&NVIC_InitS);
#endif
}

void mcu_uart1_tx(char* pdata, uint32_t len)
{
  //while( _DMA_CHN_TX->CNDTR );
  //while( !(_UART->SR & (1<<6)) );
  _DIR_OUT();
  uint32_t   i;
  for(i=0; i<len; i++){
    while( !(_UART->ISR & (1<<7)) );
    _UART->TDR = pdata[i];
  }
  while( !(_UART->ISR & (1<<6)) );
  _DIR_IN();
}

void mcu_uart1_tx_str(char* str)
{
  //while( _DMA_CHN_TX->CNDTR );
  //while( !(_UART->SR & (1<<6)) );
  _DIR_OUT();
  uint32_t   i=0;
  while(str[i]){
    while( !(_UART->ISR & (1<<7)) );
    _UART->TDR = str[i];
    i++;
  }
  while( !(_UART->ISR & (1<<6)) );
  _DIR_IN();
}

void mcu_uart1_printf(char *fmt, ...)
{
  va_list   ap;
  char      str[256];

  va_start(ap,  fmt);
  vsprintf(str, fmt, ap);
  mcu_uart1_tx_str(str);
  va_end(ap);
}
#if 0
void mcu_uart1_dma_tx(char* pdata, uint32_t len)
{
  if(len > 0){
    while( _DMA_CHN_TX->CNDTR );
    //while( !(_UART->SR & (1<<6)) );   //�����ܵ�����ʱ������ѭ��
    //the follow use for 485
    //_DIR_OUT();
    //_UART->CR1 &= ~(1<<5);      //USART_ITConfig(_UART, USART_IT_RXNE, DISABLE);
    _DMA_CHN_TX->CNDTR = len;
    _DMA_CHN_TX->CMAR  = (uint32_t)pdata;
    _DMA_CHN_TX->CCR  |= 0x01;  //DMA_Cmd(_DMA_STR, ENABLE);
  }
}
#endif
//------------------------------------------------------------------------------

//------------------------------------ISR---------------------------------------
void USART1_IRQHandler(void)
{
  uint8_t   c;
  
  if(_UART->ISR  &  (1<<5) ){  //if(USART_GetITStatus(_UART, USART_IT_RXNE) != RESET)
    _UART->ISR  &= ~(1<<5);    //read DR to clear
    c = _UART->RDR;            //USART_ReceiveData(_UART);
    c = c;
  }
  
  if(_UART->ISR  &  (1<<6) ){   //if(USART_GetITStatus(_UART, USART_IT_TC) != RESET)
    _UART->ICR = USART_FLAG_TC; //USART_ClearFlag(_UART, USART_FLAG_TC);
    
    //the follow use for 485
    //_DIR_IN();
    //_UART->CR1 &= ~(1<<6);    //USART_ITConfig(_UART, USART_IT_TC,  DISABLE);
    //_UART->CR1 |=  (1<<5);    //USART_ITConfig(_UART, USART_IT_RXNE, ENABLE);
  }
  
  if(_UART->ISR  &  (1<<4) ){  //IDLE
    _UART->ICR = USART_FLAG_IDLE;
    
  }
  
  if(_UART->ISR){
    _UART->ICR = 0xFFFFFFFF;
  }
}

#if 0
void DMA1_Channel2_3_IRQHandler(void)
{
//tx
  if(_DMA->ISR & (1<<((_DMA_NUM_TX-1)*4+1)) ){   //DMA_GetITStatus(DMA1_IT_TC4)
    _DMA->IFCR = (1<<((_DMA_NUM_TX-1)*4+1));     //DMA_ClearITPendingBit(DMA1_IT_TC4)
    
    _DMA_CHN_TX->CCR &= ~0x1;                //DMA_Cmd(_DMA_STR, DISABLE);
    //the follow use for 485
    //_UART->SR     &= ~(1<<6);  //�ر�ע������Ҫ���TCλ������485�п��ܷ�����ȫ
    //_UART->CR1    |=  (1<<6);  //USART_ITConfig(_UART, USART_IT_TC, ENABLE)
  }
  
  if(_DMA->ISR & (1<<((_DMA_NUM_TX-1)*4+3)) ){   //DMA_GetITStatus(DMA1_IT_TE4)
    _DMA->IFCR = (1<<((_DMA_NUM_TX-1)*4+3));     //DMA_ClearITPendingBit(DMA1_IT_TE4)
  }
  
//rx
  if(_DMA->ISR & (1<<((_DMA_NUM_RX-1)*4+1)) ){   //DMA_GetITStatus(DMA1_IT_TC5)
    _DMA->IFCR = (1<<((_DMA_NUM_RX-1)*4+1));     //DMA_ClearITPendingBit(DMA1_IT_TC5)
    
    //start next receive
    _DMA_CHN_RX->CCR  &= ~0x1;
    _DMA_CHN_RX->CNDTR = dbg_get_rcv_size();
    _DMA_CHN_RX->CMAR  = (uint32_t)dbg_get_rcv_addr();
    _DMA_CHN_RX->CCR  |= 0x01;  //DMA_Cmd(_DMA_STR, ENABLE);
  }
  
  if(_DMA->ISR & (1<<((_DMA_NUM_RX-1)*4+3)) ){   //DMA_GetITStatus(DMA1_IT_TE5)
    _DMA->IFCR = (1<<((_DMA_NUM_RX-1)*4+3));     //DMA_ClearITPendingBit(DMA1_IT_TE5)
  }
  
  _DMA->IFCR = 0xFFFFFFFF;
}
#endif
//------------------------------------EOF---------------------------------------


